﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WorkFlowCore.Authorization;
using WorkFlowCore.IRepositories;
using WorkFlowCore.WorkTasks;

namespace WorkFlowCore.Framework.Repositories4EF
{
    public class WorkTaskRepository4EF : BasicRepository4EF<WorkTaskInfo, Guid>, IWorkTaskRepository
    {
        private readonly WorkflowDbContext workflowDbContext;
        private readonly IWorkStepRepository workStepRepository;

        public WorkTaskRepository4EF(WorkflowDbContext workflowDbContext, IUnitOfWork unitOfWork, IWorkStepRepository workStepRepository, IWorkflowSession session) : base(workflowDbContext, unitOfWork, session)
        {
            this.workflowDbContext = workflowDbContext;
            this.workStepRepository = workStepRepository;
        }

        public async Task<PageResult<WorkTask>> GetAllTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = workflowDbContext.Set<WorkStepInfo>().Where(ws => ws.HandleUser_Id == userId).Select(ws => ws.WorkTaskId);

            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id))
            };

            var worktaskQuery = workflowDbContext.Set<WorkTaskInfo>().Where(wt => workTaskIds.Contains(wt.Id));

            if (pageSize < 1)
                result.Items = worktaskQuery.Select(w => w.ToWorkTask()).ToList();
            else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize).OrderByDescending(w=>w.CreationTime).Select(w => w.ToWorkTask()).ToList();
            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = workflowDbContext.Set<WorkStepInfo>().Where(ws => ws.HandleUser_Id == userId && ws.IsHandled).Select(ws => ws.WorkTaskId);

            var worktaskQuery = workflowDbContext.Set<WorkTaskInfo>().Where(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation).OrderByDescending(w => w.CreationTime);

            var result = new PageResult<WorkTask>
            {
                Total = worktaskQuery.Count()
            };

            if (pageSize < 1)
                result.Items = worktaskQuery.Select(w => w.ToWorkTask()).ToList();
            else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize).Select(w => w.ToWorkTask()).ToList();
            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetTasksOfStartUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var result = new PageResult<WorkTask>
            {
                Total = (await GetCountAsync(wt => wt.ModifiedUserId == userId))
            };
            var worktaskQuery = workflowDbContext.Set<WorkTaskInfo>().Where(wt => wt.ModifiedUserId == userId);

            if (pageSize < 1)
                result.Items = worktaskQuery.Select(ws=>ws.ToWorkTask()).ToList();
            else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take( pageSize).Select(w => w.ToWorkTask()).ToList();
            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetUnHandledWorkTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = workflowDbContext.Set<WorkStepInfo>().Where(ws => ws.HandleUser_Id == userId && !ws.IsHandled).Select(ws => ws.WorkTaskId); 

            var worktaskQuery = workflowDbContext.Set<WorkTaskInfo>().Where(wt => workTaskIds.Contains(wt.Id) && !wt.IsSimulation).OrderByDescending(w => w.CreationTime);

            var result = new PageResult<WorkTask>
            {
                Total = worktaskQuery.Count()
            };

            if (pageSize < 1)
                result.Items = worktaskQuery.Select(w => w.ToWorkTask()).ToList();
            else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize).Select(w => w.ToWorkTask()).ToList();
            return await Task.FromResult(result);
        }

        public async Task<PageResult<WorkTask>> GetWorkflowedTasksOfUserAsync(string userId, int pageIndex = 1, int pageSize = -1)
        {
            var workTaskIds = workflowDbContext.Set<WorkStepInfo>().Where(ws => ws.HandleUser_Id == userId && ws.IsHandled).Select(ws => ws.WorkTaskId);

            var result = new PageResult<WorkTask>
            {
                Total = await GetCountAsync(wt => workTaskIds.Contains(wt.Id))
            };

            var worktaskQuery = workflowDbContext.Set<WorkTaskInfo>().Where(wt => workTaskIds.Contains(wt.Id));

            if (pageSize < 1)
                result.Items = worktaskQuery.Select(w => w.ToWorkTask()).ToList();
            else result.Items = worktaskQuery.Skip((pageIndex - 1) * pageSize).Take(pageSize).OrderByDescending(w => w.CreationTime).Select(w => w.ToWorkTask()).ToList();
            return await Task.FromResult(result);
        }
    }
}
